home *** CD-ROM | disk | FTP | other *** search
/ Aminet 25 / Aminet 25 (1998)(GTI - Schatztruhe)[!][Jun 1998].iso / Aminet / util / arc / mpackWOS.lha / mpackppc / src / encode.c < prev    next >
C/C++ Source or Header  |  1998-04-22  |  8KB  |  243 lines

  1. /* (C) Copyright 1993,1994 by Carnegie Mellon University
  2.  * All Rights Reserved.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software
  5.  * and its documentation for any purpose is hereby granted without
  6.  * fee, provided that the above copyright notice appear in all copies
  7.  * and that both that copyright notice and this permission notice
  8.  * appear in supporting documentation, and that the name of Carnegie
  9.  * Mellon University not be used in advertising or publicity
  10.  * pertaining to distribution of the software without specific,
  11.  * written prior permission.  Carnegie Mellon University makes no
  12.  * representations about the suitability of this software for any
  13.  * purpose.  It is provided "as is" without express or implied
  14.  * warranty.
  15.  *
  16.  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
  17.  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  18.  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
  19.  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  20.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  21.  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  22.  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  23.  * SOFTWARE.
  24.  */
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <stdlib.h>
  28.  
  29. extern char *magic_look();
  30. extern char *os_genid();
  31. extern char *md5digest();
  32.  
  33. #define NUMREFERENCES 4
  34.  
  35. /*
  36.  * Encode a file into one or more MIME messages, each
  37.  * no larger than 'maxsize'.  A 'maxsize' of zero means no size limit.
  38.  * If 'applefile' is non-null, it is the first part of a multipart/appledouble
  39.  * pair.
  40.  */
  41. int encode(FILE *infile, FILE *applefile, char *fname, FILE *descfile, char *subject, char *headers, long maxsize, char *typeoverride, char *outfname)
  42. {
  43.     char *type;
  44.     FILE *outfile;
  45.     char *cleanfname, *p;
  46.     char *digest, *appledigest;
  47.     long filesize, l, written;
  48.     int thispart, numparts = 1;
  49.     int wrotefiletype = 0;
  50.     char *multipartid, *msgid, *referenceid[NUMREFERENCES];
  51.     char buf[1024];
  52.     int i;
  53.  
  54.     /* Clean up fname for printing */
  55.     cleanfname = fname;
  56. #ifdef __riscos
  57.     /* This filename-cleaning knowledge will probably
  58.      * be moved to the os layer in a future version.
  59.      */
  60.     if (p = strrchr(cleanfname, '.')) cleanfname = p+1;
  61. #else
  62.     if (p = strrchr(cleanfname, '/')) cleanfname = p+1;
  63.     if (p = strrchr(cleanfname, '\\')) cleanfname = p+1;
  64. #endif
  65.     if (p = strrchr(cleanfname, ':')) cleanfname = p+1;
  66.  
  67.     /* Find file type */
  68.     if (typeoverride) {
  69.         type = typeoverride;
  70.     }
  71.     else {
  72.         type = magic_look(infile);
  73.     }
  74.  
  75.     /* Compute MD5 digests */
  76.     digest = md5digest(infile, &filesize);
  77.     if (applefile) {
  78.         appledigest = md5digest(applefile, &l);
  79.         filesize += l;
  80.     }
  81.  
  82.     /* See if we have to do multipart */
  83.     if (maxsize) {
  84.         filesize = (filesize / 54) * 73; /* Allow for base64 expansion */
  85.  
  86.         /* Add in size of desc file */
  87.         if (descfile) {
  88.             free(md5digest(descfile, &l));      /* XXX */
  89.             filesize += l;
  90.         }
  91.  
  92.         numparts = (filesize-1000)/maxsize + 1;
  93.         if (numparts < 1) numparts = 1;
  94.     }
  95.  
  96.     multipartid = os_genid();
  97.     for (i=0; i<NUMREFERENCES; i++) {
  98.         referenceid[i] = 0;
  99.     }
  100.  
  101.     for (thispart=1; thispart <= numparts; thispart++) {
  102.         written = 0;
  103.  
  104.         /* Open output file */
  105.         if (numparts == 1) {
  106.             outfile = fopen(outfname, "w");
  107.             if (!outfile) os_perror(outfname);
  108.         }
  109.         else {
  110. #ifdef __riscos
  111.             /* Arrgh, riscos uses '.' as directory separator */
  112.             sprintf(buf, "%s/%02d", outfname, thispart);
  113. #else
  114.             sprintf(buf, "%s.%02d", outfname, thispart);
  115. #endif
  116.             outfile = fopen(buf, "w");
  117.             if (!outfile) os_perror(buf);
  118.         }
  119.         if (!outfile) return 1;
  120.         
  121.         msgid = os_genid();
  122.         fprintf(outfile, "Message-ID: <%s>\n", msgid);
  123.         fprintf(outfile, "Mime-Version: 1.0\n");
  124.         if (headers) fputs(headers, outfile);
  125.         if (numparts > 1) {
  126.             fprintf(outfile, "Subject: %s (%02d/%02d)\n", subject,
  127.                     thispart, numparts);
  128.             if (thispart == 1) {
  129.                 referenceid[0] = msgid;
  130.             }
  131.             else {
  132.                 /* Put out References: header pointing to previous parts */
  133.                 fprintf(outfile, "References: <%s>\n", referenceid[0]);
  134.                 for (i=1; i<NUMREFERENCES; i++) {
  135.                     if (referenceid[i]) fprintf(outfile, "\t <%s>\n",
  136.                                                 referenceid[i]);
  137.                 }
  138.                 for (i=2; i<NUMREFERENCES; i++) {
  139.                     referenceid[i-1] = referenceid[i];
  140.                 }
  141.                 referenceid[NUMREFERENCES-1] = msgid;
  142.             }
  143.             fprintf(outfile,
  144.                     "Content-Type: message/partial; number=%d; total=%d;\n",
  145.                     thispart, numparts);
  146.             fprintf(outfile, "\t id=\"%s\"\n", multipartid);
  147.             fprintf(outfile, "\n");
  148.         }
  149.  
  150.         if (thispart == 1) {
  151.             if (numparts > 1) {
  152.                 fprintf(outfile, "Message-ID: <%s>\n", multipartid);
  153.                 fprintf(outfile, "MIME-Version: 1.0\n");
  154.             }
  155.             fprintf(outfile, "Subject: %s\n", subject);
  156.             fprintf(outfile,
  157.                     "Content-Type: multipart/mixed; boundary=\"-\"\n");
  158.             fprintf(outfile,
  159. "\nThis is a MIME encoded message.  Decode it with \"munpack\"\n");
  160.             fprintf(outfile,
  161. "or any other MIME reading software.  Mpack/munpack is available\n");
  162.             fprintf(outfile,
  163. "via anonymous FTP in ftp.andrew.cmu.edu:pub/mpack/\n");
  164.             written = 300;
  165.  
  166.             /* Spit out description section */
  167.             if (descfile) {
  168.                 fprintf(outfile, "---\n\n");
  169.                 while (fgets(buf, sizeof(buf), descfile)) {
  170.                     /* Strip multiple leading dashes as they may become MIME
  171.                      * boundaries
  172.                      */
  173.                     p = buf;
  174.                     if (*p == '-') {
  175.                         while (p[1] == '-') p++;
  176.                     }
  177.  
  178.                     fputs(p, outfile);
  179.                     written += strlen(p);
  180.                 }
  181.                 fprintf(outfile, "\n");
  182.             }
  183.     
  184.             fprintf(outfile, "---\n");
  185.  
  186.             if (applefile) {
  187.                 fprintf(outfile,
  188.         "Content-Type: multipart/appledouble; boundary=\"=\"; name=\"%s\"\n",
  189.                         cleanfname);
  190.                 fprintf(outfile,
  191.                         "Content-Disposition: inline; filename=\"%s\"\n",
  192.                         cleanfname);
  193.                 fprintf(outfile, "\n\n--=\n");
  194.                 fprintf(outfile, "Content-Type: application/applefile\n");
  195.                 fprintf(outfile, "Content-Transfer-Encoding: base64\n");
  196.                 fprintf(outfile, "Content-MD5: %s\n\n", appledigest);
  197.                 free(appledigest);
  198.                 written += 100;
  199.             }
  200.  
  201.         }
  202.  
  203.         if (applefile && !feof(applefile)) {
  204.             if (written == maxsize) written--; /* avoid a nasty fencepost error */
  205.             written += to64(applefile, outfile,
  206.                             (thispart == numparts) ? 0 : (maxsize-written));
  207.  
  208.             if (!feof(applefile)) {
  209.                 if (outfile) fclose(outfile);
  210.                 continue;
  211.             }
  212.  
  213.             fprintf(outfile, "\n--=\n");
  214.         }
  215.  
  216.  
  217.         if (!wrotefiletype++) {
  218.             fprintf(outfile, "Content-Type: %s; name=\"%s\"\n", type,
  219.                     cleanfname);
  220.             fprintf(outfile, "Content-Transfer-Encoding: base64\n");
  221.             fprintf(outfile, "Content-Disposition: inline; filename=\"%s\"\n",
  222.                     cleanfname);
  223.             fprintf(outfile, "Content-MD5: %s\n\n", digest);
  224.             free(digest);
  225.             written += 80;
  226.         }
  227.  
  228.         if (written == maxsize) written--; /* avoid a nasty fencepost error */
  229.  
  230.         written += to64(infile, outfile,
  231.                         (thispart == numparts) ? 0 : (maxsize-written));
  232.  
  233.         if (thispart == numparts) {
  234.             if (applefile) fprintf(outfile, "\n--=--\n");
  235.             fprintf(outfile, "\n-----\n");
  236.         }
  237.         
  238.         if (outfile) fclose(outfile);
  239.     }
  240.  
  241.     return 0;
  242. }
  243.